#include "stm32_spi.h"


/* DMA传输完成标志 */
SPI_DMA_Flag_typedef SPI_DMA_Flag;


/**
  * @brief  SPI总线中断回调函数，由DMA传输完成时DMA中断函数调用
  * @note   移植时用户需要修改的接口函数
  * @param  hspi: SPI句柄
  * @retval 无
  */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
#if (STM32_SPI1_ENABLE == 1)
  if (hspi->Instance == SPI1)
  {
    /* SPI1的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI1_Transfer_Complete_Flag = SET;
  }
#endif
  
#if (STM32_SPI2_ENABLE == 1)
  if (hspi->Instance == SPI2)
  {
    /* SPI2的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI2_Transfer_Complete_Flag = SET;
  }
#endif
  
#if (STM32_SPI3_ENABLE == 1)
  if (hspi->Instance == SPI3)
  {
    /* SPI3的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI3_Transfer_Complete_Flag = SET;
  }
#endif
  
#if (STM32_SPI4_ENABLE == 1)
  if (hspi->Instance == SPI4)
  {
    /* SPI4的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI4_Transfer_Complete_Flag = SET;
  }
#endif

#if (STM32_SPI5_ENABLE == 1)
  if (hspi->Instance == SPI5)
  {
    /* SPI5的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI5_Transfer_Complete_Flag = SET;
  }
#endif

#if (STM32_SPI6_ENABLE == 1)
  if (hspi->Instance == SPI6)
  {
    /* SPI6的DMA传输完成标志置位 */
    SPI_DMA_Flag.SPI6_Transfer_Complete_Flag = SET;
  }
#endif
}


/**
  * @brief  SPI总线初始化
  * @note   移植时用户需要修改的接口函数
  * @param  SPI: SPI外设
  * @param  hspi: SPI句柄
  * @param  SPI_Mode: SPI模式，即极性和相位的设置
  * @retval 无
  */
int32_t STM32_SPI_Init(SPI_TypeDef *SPI, SPI_HandleTypeDef *hspi, uint8_t SPI_Mode)
{
  hspi->Instance = SPI;
  hspi->Init.Mode = SPI_MODE_MASTER;
  hspi->Init.Direction = SPI_DIRECTION_2LINES;
  hspi->Init.DataSize = SPI_DATASIZE_8BIT;
  if (SPI_Mode == SPI_MODE_0)
  {
    hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
  }
  else if (SPI_Mode == SPI_MODE_1)
  {
    hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi->Init.CLKPhase = SPI_PHASE_2EDGE;
  }
  else if (SPI_Mode == SPI_MODE_2)
  {
    hspi->Init.CLKPolarity = SPI_POLARITY_HIGH;
    hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
  }
  else
  {
    hspi->Init.CLKPolarity = SPI_POLARITY_HIGH;   // SPI_CPOL
    hspi->Init.CLKPhase = SPI_PHASE_2EDGE;        // SPI_CPHA
  }
  hspi->Init.NSS = SPI_NSS_SOFT;
  hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi->Init.TIMode = SPI_TIMODE_DISABLE;
  hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi->Init.CRCPolynomial = 7;
  if (HAL_SPI_Init(hspi) != HAL_OK)
  {
    Error_Handler();
  }
  
  return 0;
}


/**
  * @brief  通过SPI总线读写一个字节数据
  * @note   无
  * @param  hspi: SPI句柄
  * @param  Byte: 写入的数据
  * @retval 0
  */
int32_t STM32_SPI_TransferData(SPI_HandleTypeDef *hspi, uint8_t *TxData, uint8_t *RxData, uint16_t Length)
{
  int32_t res;

  res = HAL_SPI_TransmitReceive(hspi, TxData, RxData, Length, STM32_SPI_TIMEOUT);  

  return res;	
}


/**
  * @brief  通过SPI总线读写数据
  * @note   无
  * @param  hspi: SPI句柄
  * @param  TxData: 写入的数据
  * @param  RxData: 读取的数据
  * @param  Length: 数据长度
  * @retval 结果 0-成功，其他-失败
  */
int32_t STM32_SPI_TransferData_DMA(SPI_HandleTypeDef *hspi, uint8_t *TxData, uint8_t *RxData, uint16_t Length)
{
  uint32_t i = 0;					// 循环变量
  int32_t res;
	
  res = HAL_SPI_TransmitReceive_DMA(hspi, TxData, RxData, Length); 

#if (STM32_SPI1_ENABLE == 1)
  if (hspi->Instance == SPI1)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI1_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI1_Transfer_Complete_Flag = RESET;
  }
#endif
  
#if (STM32_SPI2_ENABLE == 1)
  if (hspi->Instance == SPI2)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI2_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI2_Transfer_Complete_Flag = RESET;
  }
#endif

#if (STM32_SPI3_ENABLE == 1)
  if (hspi->Instance == SPI3)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI3_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI3_Transfer_Complete_Flag = RESET;
  }
#endif

#if (STM32_SPI4_ENABLE == 1)
  if (hspi->Instance == SPI4)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI4_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI4_Transfer_Complete_Flag = RESET;
  }
#endif

#if (STM32_SPI5_ENABLE == 1)
  if (hspi->Instance == SPI5)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI5_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI5_Transfer_Complete_Flag = RESET;
  }
#endif

#if (STM32_SPI6_ENABLE == 1)
  if (hspi->Instance == SPI6)
  {
    /* 等待DMA传输完成 */
    while (SPI_DMA_Flag.SPI6_Transfer_Complete_Flag == RESET)
    {
      i++;
      if (i > 0xFFFFFF)
      {
        /* 超时退出 */
        return 1;
      }
    }
    SPI_DMA_Flag.SPI6_Transfer_Complete_Flag = RESET;
  }
#endif  

  return res;
}


/**
  * @brief  设置SPI总线速度
  * @note   移植时用户需要修改的接口函数
  * @param  hspi: SPI句柄
  * @param  SPI_BaudRate_Prescaler: SPI总线分频系数, SPI_BAUDRATEPRESCALER_2 ~ SPI_BAUDRATEPRESCALER_256
  * @retval 无
  */
int32_t STM32_SPI_SetSpeed(SPI_HandleTypeDef *hspi, uint32_t SPI_BaudRatePrescaler)
{
  hspi->Init.BaudRatePrescaler = SPI_BaudRatePrescaler;
	
  if (HAL_SPI_Init(hspi) != HAL_OK)
  {
    Error_Handler();
  }
	
  return 0;
}








static int32_t BSP_SPI_Init(void *BSP_SPI_Handle, bsp_spi_mode_t Mode, uint32_t Freq);
static int32_t BSP_SPI_DeInit(void *BSP_SPI_Handle);
static int32_t BSP_SPI_SetMode(void *BSP_SPI_Handle, bsp_spi_mode_t Mode);
static int32_t BSP_SPI_SetFreq(void *BSP_SPI_Handle, uint32_t Freq);
static int32_t BSP_SPI_Transmit(void *BSP_SPI_Handle, void *TxData, uint32_t Size);
static int32_t BSP_SPI_Receive(void *BSP_SPI_Handle, void *RxData, uint32_t Size);
static int32_t BSP_SPI_Transfer(void *BSP_SPI_Handle, void *TxData, void *RxData, uint32_t Size);
static int32_t BSP_SPI_Transmit_DMA(void *BSP_SPI_Handle, void *TxData, uint32_t Size);
static int32_t BSP_SPI_Receive_DMA(void *BSP_SPI_Handle, void *RxData, uint32_t Size);
static int32_t BSP_SPI_Transfer_DMA(void *BSP_SPI_Handle, void *TxData, void *RxData, uint32_t Size);


#if (STM32_SPI1_ENABLE == 1)
bsp_spi_t BSP_SPI1 = 
{
  &hspi1,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif

#if (STM32_SPI2_ENABLE == 1)
bsp_spi_t BSP_SPI2 = 
{
  &hspi2,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif

#if (STM32_SPI3_ENABLE == 1)
bsp_spi_t BSP_SPI3 = 
{
  &hspi3,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif

#if (STM32_SPI4_ENABLE == 1)
bsp_spi_t BSP_SPI4 = 
{
  &hspi4,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif

#if (STM32_SPI5_ENABLE == 1)
bsp_spi_t BSP_SPI5 = 
{
  &hspi5,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif

#if (STM32_SPI6_ENABLE == 1)
bsp_spi_t BSP_SPI6 = 
{
  &hspi6,
  BSP_SPI_Init,
  BSP_SPI_DeInit,
  BSP_SPI_SetMode,
  BSP_SPI_SetFreq, 
  BSP_SPI_Transmit,
  BSP_SPI_Receive,
  BSP_SPI_Transfer,
  BSP_SPI_Transmit_DMA,
  BSP_SPI_Receive_DMA,
  BSP_SPI_Transfer_DMA,
};
#endif


/**
  * @brief  BSP SPI总线初始化
  * @note   抽象层
  * @param  BSP_SPI_Handle: BSP SPI句柄
  * @param  Mode: SPI模式，即极性和相位的设置
  * @param  Freq: 时钟
  * @retval 0-成功，其他-失败
  */
static int32_t BSP_SPI_Init(void *BSP_SPI_Handle, bsp_spi_mode_t Mode, uint32_t Freq)
{
  int32_t res;

  res = BSP_SPI_SetMode(BSP_SPI_Handle, Mode);
  if (res != 0)
  {
    return res;
  }
  
  res = BSP_SPI_SetFreq(BSP_SPI_Handle, Freq);
  return res;
}


static int32_t BSP_SPI_DeInit(void *BSP_SPI_Handle)
{
  return 0;
}


static int32_t BSP_SPI_SetMode(void *BSP_SPI_Handle, bsp_spi_mode_t Mode)
{
  int32_t res;
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  SPI_HandleTypeDef *bsp_hspi = (SPI_HandleTypeDef *)bsp_spi_handle->spi_handle;
  
  STM32_SPI_Init(bsp_hspi->Instance, bsp_hspi, Mode);
  return res;
}


static int32_t BSP_SPI_SetFreq(void *BSP_SPI_Handle, uint32_t Freq)
{
  int32_t res;
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  if (Freq <= 1000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_256);
  }
  else if (Freq <= 2000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_32);
  }
  else if (Freq <= 5000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_16);
  }
  else if (Freq <= 10000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_8);
  }
  else if (Freq <= 20000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_4);
  }
  else if (Freq <= 30000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_4);
  }
  else if (Freq <= 40000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_4);
  }
  else if (Freq <= 50000000)
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_4);
  }
  else  /* > 50MHz */
  {
    STM32_SPI_SetSpeed(bsp_spi_handle->spi_handle, SPI_BAUDRATEPRESCALER_2);
  }
  
  return res;
}


uint8_t spi_data_temp[1024];
static int32_t BSP_SPI_Transmit(void *BSP_SPI_Handle, void *TxData, uint32_t Size)
{
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  STM32_SPI_TransferData(bsp_spi_handle->spi_handle, TxData, spi_data_temp, Size);
  
  return 0;
}


static int32_t BSP_SPI_Receive(void *BSP_SPI_Handle, void *RxData, uint32_t Size)
{
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  memset(spi_data_temp, 0xFF, 1024);
  
  STM32_SPI_TransferData(bsp_spi_handle->spi_handle, spi_data_temp, RxData, Size);
  
  return 0;
}


static int32_t BSP_SPI_Transfer(void *BSP_SPI_Handle, void *TxData, void *RxData, uint32_t Size)
{
  int32_t res;
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  res = STM32_SPI_TransferData(bsp_spi_handle->spi_handle, TxData, RxData, Size);
  
  return res;
}


static int32_t BSP_SPI_Transmit_DMA(void *BSP_SPI_Handle, void *TxData, uint32_t Size)
{
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  STM32_SPI_TransferData_DMA(bsp_spi_handle->spi_handle, TxData, spi_data_temp, Size);
  
  return 0;
}


static int32_t BSP_SPI_Receive_DMA(void *BSP_SPI_Handle, void *RxData, uint32_t Size)
{
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  memset(spi_data_temp, 0xFF, 1024);
  
  STM32_SPI_TransferData_DMA(bsp_spi_handle->spi_handle, spi_data_temp, RxData, Size);
  
  return 0;
}


static int32_t BSP_SPI_Transfer_DMA(void *BSP_SPI_Handle, void *TxData, void *RxData, uint32_t Size)
{
  int32_t res;
  bsp_spi_t *bsp_spi_handle = (bsp_spi_t *)BSP_SPI_Handle;
  
  res = STM32_SPI_TransferData_DMA(bsp_spi_handle->spi_handle, TxData, RxData, Size);
  
  return res;
}


